package com.base.commons.tools.utils;


import com.base.commons.tools.rest.config.HttpClientRequestFactory;
import org.apache.commons.codec.binary.Base64;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

/**
 * @author carl
 */
public final class HttpConnectUtil {
    private static RestTemplate httpClientTemplate;

    static {
        httpClientTemplate = (RestTemplate) SpringContextUtil.getBean("httpClientTemplate");
    }

    /**
     * @param requestParam  请Resttemplate进行Basic认证
     * @param url           HTTP 请求地址
     * @param headers        请求头，没有请求头的设置为null即可
     * @param requestMethod 请求方法 GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
     * @param responseType          响应类型，根据服务接口的返回类型决定 map,string
     * @param object：支持PathVariable类型的数据。
     * @param username：用户名。
     * @param password：密码。
     * @return 返回的是Object类型 其中ResponseEntity.getBody()请求返回json内容；ResponseEntity.getStatusCodeValue() 请求返回http状态码
     */
    public static <T> ResponseEntity  tempHttp(Object requestParam, String url, HttpHeaders headers, String requestMethod, Map<String, ?> object, Class<T> responseType, String username, String password) {
        headers = setDefaultHeaders(headers);
        String plainCreds = username+":"+password;
        byte[] plainCredsBytes = plainCreds.getBytes();
        byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
        String base64Creds = new String(base64CredsBytes);
        headers.add("Authorization", "Basic " + base64Creds);
        return getResponseEntity(requestParam, url, headers, requestMethod, object, responseType);

    }

    private static <T> ResponseEntity getResponseEntity(Object requestParam, String url, HttpHeaders headers, String requestMethod, Map<String, ?> object, Class<T> responseType) {
        HttpEntity<?> requestEntity = new HttpEntity<>(requestParam, headers);
        HttpMethod  httpMethod= HttpMethod.resolve(requestMethod.toUpperCase());
        return httpClientTemplate.exchange(url, httpMethod, requestEntity, responseType,object);
    }

    /**
     * @param requestParam  请求时带的实体类，参数等
     * @param url           HTTP 请求地址
     * @param headers        请求头，没有请求头的设置为null即可
     * @param requestMethod 请求方法 GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
     * @param object：支持PathVariable类型的数据。
     *@param responseType：返回数据类型。
     *
     * @return 返回的是Object类型 其中ResponseEntity.getBody()请求返回json内容；ResponseEntity.getStatusCodeValue() 请求返回http状态码
     */
    public static <T> ResponseEntity tempHttp(Object requestParam, String url, HttpHeaders headers, String requestMethod, Map<String, ?> object, Class<T> responseType) {
        headers = setDefaultHeaders(headers);
        return getResponseEntity(requestParam, url, headers, requestMethod, object, responseType);
    }

    public static HttpHeaders setDefaultHeaders(HttpHeaders headers){
        if(headers==null){
            headers = new HttpHeaders();
        }
        if(!headers.containsKey(HttpHeaders.CONTENT_TYPE)){
            headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        }

        return headers;
    }
    /**
     * @param requestParam  请求时带的实体类，参数等
     * @param url           HTTP 请求地址
     * @param headers        请求头，没有请求头的设置为null即可
     * @param requestMethod 请求方法 GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
     * @param object：支持PathVariable类型的数据。
     * @param responseType：返回数据类型
     * @param connectTimeout：客户端和服务器建立连接超时
     * @param readTimeout：指客户端从服务器读取数据包的间隔超时时间
     * @return 返回的是Object类型 其中ResponseEntity.getBody()请求返回json内容；ResponseEntity.getStatusCodeValue() 请求返回http状态码
     */
    public static <T> ResponseEntity tempHttp(Object requestParam, String url, HttpHeaders headers, String requestMethod, Map<String, ?> object, Class<T> responseType,
                                              Integer connectTimeout,Integer readTimeout) {
         // 设置当前请求超时时间
        Map<String,Integer> map = new HashMap<>(2);
        map.put(HttpClientRequestFactory.CONNECT_TIMEOUT,connectTimeout);
        map.put(HttpClientRequestFactory.SOCKET_TIMEOUT,readTimeout);
        HttpClientRequestFactory.socketTimeoutThreadLocal.set(map);
        try {
            return  tempHttp( requestParam,  url,  headers,  requestMethod, object,  responseType);
        } finally {
            // 清理ThreadLocal中超时时间
            HttpClientRequestFactory.socketTimeoutThreadLocal.remove();
        }
    }
}